package com.kunpan.admin.config;

import com.kunpan.admin.aop.AutoFillAspect;
import com.kunpan.admin.common.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PreDestroy;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;


/*
* 自定义线程池
* */
@Configuration
public class ThreadPoolConfig {
    private static final Logger log = LoggerFactory.getLogger(AutoFillAspect.class);

    private final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    /**
     * 通用线程池
     * */
    @Bean("taskExecutor")
    public Executor getAsyncExecutor() {
        executor.setCorePoolSize(8); //线程池创建的核心线程数
        executor.setMaxPoolSize(24); //线程池最大线程池数量，当任务数超过corePoolSize以及缓冲队列也满了以后才会申请的线程数量
        executor.setQueueCapacity(100);//设置线程池的任务队列容量，即当核心线程数已满时，任务将被放入这个队列中等待执行
        executor.setKeepAliveSeconds(60); //允许线程空闲时间60秒
        executor.setThreadNamePrefix("AsyncTask-");
        executor.initialize();
        // 线程池对拒绝任务(无线程可用)的处理策略->当线程池和队列都满时，新任务将由调用线程执行，避免任务被直接丢弃。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    /**
     * 执行周期性或定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService()
    {
        return new ScheduledThreadPoolExecutor(10,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
                new ThreadPoolExecutor.CallerRunsPolicy())
        {
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }

    @PreDestroy
    public void destroyExecutor() {
        log.info("---线程池关闭成功---");
        executor.shutdown();
    }
}